﻿using System.ComponentModel.Composition;
using Cubicle.Core.Interfaces;
using Cubicle.Core.Processors.Parameter;

namespace Cubicle.Core.Processors.Invoke
{
    [Export("Cubicle.Processors.Invoke.SetFieldProcessor", typeof(IProcessor<InstructionRequest>))]
    [ExportMetadata("Name", "SetFieldProcessor")]
    [ExportMetadata("Description", "Peforms 'set' operations on a target field")]
    public class SetFieldProcessor : InstructionRequestProcessor
    {
        [Import]
        private ParameterProcessor _parameterProcessor;

        [ImportingConstructor]
        public SetFieldProcessor()
            : base(RequestType.Virtual | RequestType.Static | RequestType.Field | RequestType.Set) { }

        #region Overrides of Processor<InstructionRequest>

        public override InstructionRequest ConditionalProcess(InstructionRequest request)
        {
            if (request.TargetField == null)
            {
                request.Fail("No field to retrieve.");
                return request;
            }
            var targetType = request.TargetField.FieldType;
            var parRequest = new ParameterRequest(targetType, request.Inst.Parameters[0]);
            _parameterProcessor.Process(parRequest);

            // Before accessor event
            var args = new InstructionEventArgs(InstructionEventType.BeforeAccessor, request);
            RaiseProcessorEvent(this, args);

            // Set field
            request.TargetField.SetValue(request.Target, parRequest.Result);

            // After accessor event
            args = new InstructionEventArgs(InstructionEventType.AfterAccessor, request);
            RaiseProcessorEvent(this, args);

            request.Complete(null);
            return request;
        }

        #endregion
    }
}